package com.cjl.damin.service.impl;

import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cjl.admin.dtos.AdminInfoDto;
import com.cjl.admin.dtos.AdminLoginDto;
import com.cjl.admin.pojos.Admin;
import com.cjl.common.dtos.ResponseResult;
import com.cjl.common.enums.HttpEnums;
import com.cjl.damin.mapper.AdminMapper;
import com.cjl.damin.service.AdminService;
import com.cjl.utils.common.JwtUtil;
import com.cjl.utils.common.RandomStrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Mapper;
import org.omg.CORBA.DATA_CONVERSION;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author cjl
 * @version v1.0
 * @description TODO
 * @createTime 2023/2/19 10:59
 */

@Transactional
@Component
@Slf4j
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {


    /**
     * 管理员登录/注册  status： 0--注册  1--登录
     *
     * @param adminLoginDto 管理员登录dto
     * @return ResponseResult
     */
    @Override
    public ResponseResult login(AdminLoginDto adminLoginDto) {
        //检查参数
        if (checkParams(adminLoginDto)) return ResponseResult.errorResult(HttpEnums.PARAMS_INVALID);

        //获取参数
        Short status = adminLoginDto.getStatus();
        String account = adminLoginDto.getAccount();
        String password = adminLoginDto.getPassword();

        //根据account获取管理员
        Admin dbAdmin = getAdminByAccount(account);


        //判断是登录还是注册
        if (status == 0) {
            //注册

            //判断管理员是否存在
            if (dbAdmin != null) return ResponseResult.errorResult(HttpEnums.ADMIN_ALREADY_EXIST);

            //注册新管理员
            String salt = RandomStrUtil.randomStr();
            String dbPassword = DigestUtils.md5DigestAsHex((password + salt).getBytes());
            Admin newAdmin = Admin.builder()
                    .salt(salt)
                    .account(account)
                    .createdTime(new Date())
                    .password(dbPassword)
                    .build();

            //保存数据到mysql
            boolean result = save(newAdmin);
            if (!result) return ResponseResult.errorResult(HttpEnums.DB_UPDATE_DATA_ERROR, "管理员注册失败");

            //屏蔽敏感信息
            blockSensitiveMessage(newAdmin);
            return ResponseResult.okResult(newAdmin);

        } else if (status == 1) {
            //登录
            //判断管理员是否存在
            if (dbAdmin == null) return ResponseResult.errorResult(HttpEnums.ADMIN_NOT_EXIST);

            //比对密码
            String dbPassword = dbAdmin.getPassword();
            String salt = dbAdmin.getSalt();
            password = DigestUtils.md5DigestAsHex((password + salt).getBytes());
            if (!password.equals(dbPassword)) return ResponseResult.errorResult(HttpEnums.DB_PASSWORD_ERROR);

            //登录
            dbAdmin.setUpdatedTime(new Date());
            updateById(dbAdmin);

            //根据id随机生成token
            String token = JwtUtil.getToken(dbAdmin.getId().longValue());

            //封装数据
            Map<String, Object> data = new HashMap<>();
            //屏蔽敏感信息
            blockSensitiveMessage(dbAdmin);
            data.put("admin", dbAdmin);
            data.put("token", token);

            return ResponseResult.okResult(data);
        } else return ResponseResult.errorResult(HttpEnums.PARAMS_INVALID, "非法状态值");
    }

    /**
     * 修改密码 status： 2--修改密码
     *
     * @param adminLoginDto 管理员登录dto
     * @return ResponseResult
     */
    @Override
    public ResponseResult modifyPassword(AdminLoginDto adminLoginDto) {
        //检查参数
        if (checkParams(adminLoginDto)) return ResponseResult.errorResult(HttpEnums.PARAMS_INVALID);

        //判断是否是修改密码操作
        Short status = adminLoginDto.getStatus();
        if (status != 2) return ResponseResult.errorResult(HttpEnums.PARAMS_INVALID, "非法操作");

        //获取参数
        String account = adminLoginDto.getAccount();
        String password = adminLoginDto.getPassword();

        //根据account获取管理员
        Admin dbAdmin = getAdminByAccount(account);

        //判断管理员是否存在
        if (dbAdmin == null) return ResponseResult.errorResult(HttpEnums.ADMIN_NOT_EXIST);

        //获取盐值，修改密码
        String salt = dbAdmin.getSalt();
        String dbPassword = DigestUtils.md5DigestAsHex((password + salt).getBytes());

        //修改相关属性
        dbAdmin.setUpdatedTime(new Date());
        dbAdmin.setPassword(dbPassword);

        //更新管理员信息
        boolean result = updateById(dbAdmin);
        //判断是否更新成功
        if (!result) return ResponseResult.errorResult(HttpEnums.DB_UPDATE_DATA_ERROR, "管理员修改密码出错");

        //屏蔽敏感信息
        blockSensitiveMessage(dbAdmin);
        return ResponseResult.okResult(dbAdmin);

    }

    /**
     * 修改管理员身份信息
     * @param adminInfoDto 管理员dto
     * @return ResponseResult
     */
    @Override
    public ResponseResult modifyAdminInfo(AdminInfoDto adminInfoDto) {
        return null;
    }

    /**
     * 屏蔽敏感信息
     *
     * @param admin 管理员
     */
    private void blockSensitiveMessage(Admin admin) {
        admin.setId(null);
        admin.setPassword(null);
        admin.setSalt(null);
    }

    private Admin getAdminByAccount(String account) {
        return getOne(new LambdaQueryWrapper<Admin>().eq(Admin::getAccount, account));
    }

    /**
     * 检查adminLoginDto参数是否有效
     *
     * @param adminLoginDto 管理员登录dto
     * @return boolean
     */
    private boolean checkParams(AdminLoginDto adminLoginDto) {
        return adminLoginDto == null
                || StringUtils.isBlank(adminLoginDto.getAccount())
                || StringUtils.isBlank(adminLoginDto.getPassword())
                || adminLoginDto.getStatus() == null;
    }
}
